﻿using System;
using Microsoft.Practices.Unity;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Sern.Abstracts.Tracker.DataContracts;
using Sern.Common;
using Sern.ServiceImplementation.TrackerDefinition.Data;
using Sern.ServiceImplementation.TrackerDefinition.Service;

namespace Sern.Test.ServiceImplementation.TrackerDefinition.Service
{
    [TestClass]
    public class Tracker_IsMinimumRedundancySatisfied
    {
        [TestInitialize]
        public void Init()
        {
            ComponentLocator.Reset();

            ComponentLocator.Unity.RegisterInstance(
                RepositoryFactory.CreateStub<Client>());

            ComponentLocator.Unity.RegisterInstance(
                RepositoryFactory.CreateStub<KeyTree>());

            ComponentLocator.Unity.RegisterInstance(
                RepositoryFactory.CreateStub<KeyAtClientLog>());

            ComponentLocator.Unity.RegisterTestInstance(Guid.NewGuid(), "JobId");

            Guid client1Id, client2Id, client3Id;

            client1Id = Guid.NewGuid();
            client2Id = Guid.NewGuid();
            client3Id = Guid.NewGuid();
            Guid key1 = Guid.NewGuid();
            Guid redundancyKey1 = Guid.NewGuid();
           
            ComponentLocator.Unity.RegisterInstance("Key", key1);
            ComponentLocator.Unity.RegisterInstance("RedundancyKey", redundancyKey1);

            ComponentLocator.Unity.Resolve<IRepository<KeyAtClientLog>>()
                .AddMany(
                    new KeyAtClientLog[]{
                        new KeyAtClientLog
                            {
                                ClientId = client1Id,
                                KeyId = key1,
                                RedundancyKey = redundancyKey1,
                                State = (int) ProcessingStage.Processing,
                                Id = Guid.NewGuid()
                            },
                        new KeyAtClientLog
                            {
                                ClientId = client2Id,
                                KeyId = key1,
                                RedundancyKey = redundancyKey1,
                                State = (int) ProcessingStage.Processing,
                                Id = Guid.NewGuid()
                            },
                        new KeyAtClientLog
                            {
                                ClientId = client3Id,
                                KeyId = key1,
                                RedundancyKey = redundancyKey1,
                                State = (int) ProcessingStage.Initiated,
                                Id = Guid.NewGuid()
                            },
                    });

            ComponentLocator.Unity.Resolve<IRepository<Client>>()
                .AddMany(new[]
                    {
                        new ClientStatusInfo
                            {
                                Id = client1Id,
                                JobId = ComponentLocator.Unity.ResolveTest<Guid>("JobId"),
                                Uri = "http://myService1",
                                ClientHostUri = "http://myServiceHost1",
                                KeyShape = "keyShape",
                                ValueShape = "valueShape",
                                LastAlivePing = DateTime.UtcNow,
                                StartOfSubscription = DateTime.UtcNow,
                                Type = (int) ClientType.Filter,
                                IdHash = 0
                            },
                        new ClientStatusInfo
                            {
                                Id = client2Id,
                                JobId = ComponentLocator.Unity.ResolveTest<Guid>("JobId"),
                                Uri = "http://myService1",
                                ClientHostUri = "http://myServiceHost2",
                                KeyShape = "keyShape",
                                ValueShape = "valueShape",
                                LastAlivePing = DateTime.UtcNow,
                                StartOfSubscription = DateTime.UtcNow,
                                Type = (int) ClientType.Filter,
                                IdHash = 0
                            },
                        new ClientStatusInfo
                            {
                                JobId = ComponentLocator.Unity.ResolveTest<Guid>("JobId"),
                                Id = client3Id,
                                Uri = "http://myService1",
                                ClientHostUri = "http://myServiceHost3",
                                KeyShape = "keyShape",
                                ValueShape = "valueShape",
                                LastAlivePing = DateTime.UtcNow,
                                StartOfSubscription = DateTime.UtcNow,
                                Type = (int) ClientType.Filter,
                                IdHash = 0
                            },
                    });
        }

        
        [TestMethod]
        [Description("While there are more than 2 copies of the kvp pair in the mock system, each filter client must receive a copy for redundancy requirement to be fully satisfied.")]
        public void MinimumRedundancyOnlyWhenEveryFilterGetsAtLeastACopy()
        {
            var isRedundancySatisfied = new Tracker().IsMinimumRedundancySatisfied(
                ComponentLocator.Unity.ResolveTest<Guid>("JobId"),
                ComponentLocator.Unity.Resolve<Guid>("Key"),
                ComponentLocator.Unity.Resolve<Guid>("RedundancyKey"),
                ClientType.Filter);

            //TODO: Gotta work on assigning the hash to the filter, if less than redundancy min. 
            //TODO: Gotta modify filter client count to ignore active, otherwise redundancy not properly honored for filter purposes.
            Assert.IsFalse(isRedundancySatisfied);
        }
    }
}
